import { type TreeOption } from "naive-ui";
import { Icon } from "@iconify/vue";
import { menuApi } from "@/api";
import { Emits } from "./types";
import { BUTTON_CODE, menuItemColorMapping } from "../config";

export interface DropdownProps {
  show: boolean;
  x: number;
  y: number;
  options: { key: string; label: string }[];
}

export const useCreateTree = () => {
  /** 右击菜单弹出选择框 */
  const handleContextMenu = async (e: MouseEvent, menu: Menu) => {
    e.preventDefault();
    // 若右击按钮项，则不弹出选择框
    if (menu.type == BUTTON_CODE) return;
    rightClickMenu.value = menu;

    dropdown.value.show = false;
    await nextTick();
    dropdown.value.show = true;
    dropdown.value.x = e.clientX;
    dropdown.value.y = e.clientY;
  };

  const menu2TreeOption = (menus?: Menu[]): TreeOption[] => {
    if (!menus) return [];
    return menus.map((menu) => ({
      key: menu.id,
      label: menu.name,
      isLeaf: !menu.children || !menu.children.length,
      children: menu2TreeOption(menu.children),
      meta: menu,
      prefix: () => {
        if (menu.icon)
          return (
            <div onContextmenu={(e) => handleContextMenu(e, menu)}>
              <Icon class="ml-5 text-16" icon={menu.icon} />
            </div>
          );
      },
    }));
  };

  const loading = ref(false);
  const menuTree = ref<TreeOption[]>([]);
  const rightClickMenu = ref<Menu>();
  const dropdown = ref<DropdownProps>({
    show: false,
    x: 0,
    y: 0,
    options: [{ key: "addChildNode", label: "添加子菜单" }],
  });

  const renderLabel = ({ option }: { option: TreeOption }) => {
    const menu = option.meta as Menu;
    return (
      <div
        style={{ color: menuItemColorMapping[menu.type!] }}
        onContextmenu={(e) => handleContextMenu(e, menu)}
      >
        {option.label}
      </div>
    );
  };

  const getMenuTree = async () => {
    loading.value = true;
    try {
      const { data } = await menuApi.getTree();
      menuTree.value = menu2TreeOption(data);
    } finally {
      loading.value = false;
    }
  };
  return {
    dropdown,
    rightClickMenu,
    menuTree,
    loading,
    renderLabel,
    getMenuTree,
  };
};

export const useSelcetOption = (
  rightClickMenu: Ref<Menu | undefined>,
  data: WritableComputedRef<Menu | undefined>,
  emits: Emits
) => {
  const selectedKeys = ref<string[]>([]);

  const addChildNode = () => {
    selectedKeys.value = [rightClickMenu.value!.id!];
    data.value = rightClickMenu.value;
    emits("handleAddChild");
  };
  const menuTreeNodeProps = ({ option }: { option: TreeOption }) => ({
    onClick() {
      data.value = option.meta as Menu;
    },
  });

  const handleAddSelect = (key: "add-root" | "add-child") => {
    if (key == "add-child") emits("handleAddChild");
    else emits("handleAddRoot");
  };
  return {
    selectedKeys,
    addChildNode,
    menuTreeNodeProps,
    handleAddSelect,
  };
};

export const useExpand = (menuTree: Ref<TreeOption[]>) => {
  const expandedKeys = ref<string[]>([]);
  const handlePack = () => {
    if (expandedKeys.value.length) {
      expandedKeys.value = [];
    } else {
      expandedKeys.value = expandFlatMap(menuTree.value);
    }
  };
  const expandFlatMap = (menus?: TreeOption[]): string[] => {
    if (!menus || !menus.length) return [];
    return menus.flatMap((menu) => [
      menu.key as string,
      ...expandFlatMap(menu.children),
    ]);
  };
  return {
    expandedKeys,
    handlePack,
  };
};
